/**
 * 
 */
package com.xored.glance.search.engine;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * @author Yuri Strot
 * 
 */
public class SearchUtils {

	public static Pattern createPattern(String pattern,
			boolean isCaseSensitive, boolean isPrefix)
			throws PatternSyntaxException {
		return createPattern(pattern, false, true, isCaseSensitive, isPrefix);
	}

	/**
	 * Creates a pattern element from the pattern string which is either a
	 * reg-ex expression or in our old 'StringMatcher' format.
	 * 
	 * @param pattern
	 *            The search pattern
	 * @param isRegex
	 *            <code>true</code> if the passed string already is a reg-ex
	 *            pattern
	 * @param isStringMatcher
	 *            <code>true</code> if the passed string is in the StringMatcher
	 *            format.
	 * @param isCaseSensitive
	 *            Set to <code>true</code> to create a case insensitive pattern
	 * @param isPrefix
	 *            <code>true</code> to create a pattern that requires a word
	 *            boundary at the beginning and the end.
	 * @return The created pattern
	 * @throws PatternSyntaxException
	 */
	public static Pattern createPattern(String pattern, boolean isRegex,
			boolean isStringMatcher, boolean isCaseSensitive, boolean isPrefix)
			throws PatternSyntaxException {
		if (isRegex) {
			if (isPrefix) {
				StringBuffer buffer = new StringBuffer(pattern.length() + 10);
				buffer.append("\\b(?:").append(pattern).append(")\\b"); //$NON-NLS-1$ //$NON-NLS-2$
				pattern = buffer.toString();
			}
		} else {
			int len = pattern.length();
			StringBuffer buffer = new StringBuffer(len + 10);
			if (len > 0 && isPrefix) {
				buffer.append("(\\A|\\W)");
			}
			appendAsRegEx(isStringMatcher, pattern, buffer);
			pattern = buffer.toString();
		}

		int regexOptions = Pattern.MULTILINE;
		if (!isCaseSensitive) {
			regexOptions |= Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
		}
		return Pattern.compile(pattern, regexOptions);
	}

	public static StringBuffer appendAsRegEx(boolean isStringMatcher,
			String pattern, StringBuffer buffer) {
		boolean isEscaped = false;
		for (int i = 0; i < pattern.length(); i++) {
			char c = pattern.charAt(i);
			switch (c) {
			// the backslash
			case '\\':
				// the backslash is escape char in string matcher
				if (isStringMatcher && !isEscaped) {
					isEscaped = true;
				} else {
					buffer.append("\\\\"); //$NON-NLS-1$
					isEscaped = false;
				}
				break;
			// characters that need to be escaped in the regex.
			case '(':
			case ')':
			case '{':
			case '}':
			case '.':
			case '[':
			case ']':
			case '$':
			case '^':
			case '+':
			case '|':
				if (isEscaped) {
					buffer.append("\\\\"); //$NON-NLS-1$
					isEscaped = false;
				}
				buffer.append('\\');
				buffer.append(c);
				break;
			case '?':
				if (isStringMatcher && !isEscaped) {
					buffer.append('.');
				} else {
					buffer.append('\\');
					buffer.append(c);
					isEscaped = false;
				}
				break;
			case '*':
				if (isStringMatcher && !isEscaped) {
					buffer.append(".*"); //$NON-NLS-1$
				} else {
					buffer.append('\\');
					buffer.append(c);
					isEscaped = false;
				}
				break;
			default:
				if (isEscaped) {
					buffer.append("\\\\"); //$NON-NLS-1$
					isEscaped = false;
				}
				buffer.append(c);
				break;
			}
		}
		if (isEscaped) {
			buffer.append("\\\\"); //$NON-NLS-1$
			isEscaped = false;
		}
		return buffer;
	}

}
